Skip to content

Conversation

@fnordahl
Copy link

Scripts exist that may call one of the multi-binary entry points with argument 0 set to some other value than the name of the entry point.

One example is the Open vSwitch testsuite which makes use of /bin/true as an argument to the bash builtin exec to check whether it supports the '-a' argument [0].

In this situation coreutils will print usage on standard output, which makes unnecessary noise.

Printing usage on standard error, which is customary for other tools, allows the script to succeed.

0: https://github.com/openvswitch/ovs/blob/28064e9fa50d/tests/ovs-macros.at#L199

Scripts exist that may call one of the multi-binary entry points
with argument 0 set to some other value than the name of the entry
point.

One example is the Open vSwitch testsuite which makes use of
/bin/true as an argument to the bash builtin `exec` to check
whether it supports the '-a' argument [0].

In this situation coreutils will print usage on standard output,
which makes unnecessary noise.

Printing usage on standard error, which is customary for other
tools, allows the script to succeed.

0: https://github.com/openvswitch/ovs/blob/28064e9fa50d/tests/ovs-macros.at#L199
Signed-off-by: Frode Nordahl <[email protected]>
@github-actions
Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/tee (passes in this run but fails in the 'main' branch)

@Ecordonnier Ecordonnier self-assigned this Jan 6, 2026
@github-actions
Copy link

github-actions bot commented Jan 7, 2026

GNU testsuite comparison:

GNU test failed: tests/runcon/runcon-compute. tests/runcon/runcon-compute is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)
Note: The gnu test tests/basenc/bounded-memory is now being skipped but was previously passing.
Note: The gnu test tests/cp/nfs-removal-race is now being skipped but was previously passing.

@Ecordonnier
Copy link
Collaborator

Ecordonnier commented Jan 7, 2026

@fnordahl As far as I can tell, GNU coreutils prints the --help text on stdout, not on stderr. So based on that I would reject the PR, unless I'm missing something? uutils-coreutils should behave exactly the same way than GNU coreutils.

ecordonnier@lj8k2dq3:~/dev/gnu$ ./src/coreutils --version
coreutils (GNU coreutils) 9.9.160-0fcdd
Copyright (C) 2026 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Alex Deymo.

ecordonnier@lj8k2dq3:~/dev/gnu$ ./src/coreutils --help 2>/dev/null
Usage: ./src/coreutils --coreutils-prog=PROGRAM_NAME [PARAMETERS]... 
Execute the PROGRAM_NAME built-in program with the given PARAMETERS.

      --help        display this help and exit
      --version     output version information and exit

Built-in programs:
 [ b2sum base32 base64 basename basenc cat chcon chgrp chmod chown chroot cksum comm cp csplit cut date dd df dir dircolors dirname du echo env expand expr factor false fmt fold ginstall groups head hostid id join link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup nproc numfmt od paste pathchk pinky pr printenv printf ptx pwd readlink realpath rm rmdir runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf sleep sort split stat stdbuf stty sum sync tac tail tee test timeout touch tr true truncate tsort tty uname unexpand uniq unlink users vdir wc who whoami yes

Use: './src/coreutils --coreutils-prog=PROGRAM_NAME --help' for individual program help.

Report bugs to: [email protected]
GNU coreutils home page: <https://www.gnu.org/software/coreutils/>
General help using GNU software: <https://www.gnu.org/gethelp/>
Full documentation <https://www.gnu.org/software/coreutils/coreutils>
or available locally via: info '(coreutils) Multi-call invocation'
ecordonnier@lj8k2dq3:~/dev/gnu$ ./src/coreutils --help >/dev/null

ecordonnier@lj8k2dq3:~/dev/gnu$ 

@Ecordonnier Ecordonnier self-requested a review January 7, 2026 11:56
@fnordahl
Copy link
Author

fnordahl commented Jan 7, 2026

@fnordahl As far as I can tell, GNU coreutils prints the --help text on stdout, not on stderr. So based on that I would reject the PR, unless I'm missing something? uutils-coreutils should behave exactly the same way than GNU coreutils.

Let's see, its been a while so let me see if I can remember this.

The problem appears to root in the fact that many existing scripts change argv[0] when calling one of the coreutils, in this instance true, which creates the change in behavior.

Example:

ubuntu@r:~$ bash -c "exec -a myname /usr/bin/gnutrue" ; echo $?
0

ubuntu@r:~$ bash -c "exec -a myname /usr/lib/cargo/bin/coreutils/true" ; echo $?
Security violation: Requested utility `myname` does not match executable name:
  /usr/lib/cargo/bin/coreutils/true
1

Since the last time I looked at this coreutils appears to have changed to print this security violation instead of the usage.

You also appear to be correct in that the stdout vs. stderr assertion is incorrect, not sure how I came to that conclusion.

Anyway, this is a breaking change in coreutils.

It appears that true is one of the tools that are kept from GNU for the time being, so I guess we'll just continue like that?

ubuntu@r:~$ ls -l /usr/bin | egrep "(\-> gnu)"
lrwxrwxrwx   1 root root           8 Sep 26 18:16 chmod -> gnuchmod
lrwxrwxrwx   1 root root           8 Sep 26 18:16 chown -> gnuchown
lrwxrwxrwx   1 root root           5 Sep 26 18:16 cp -> gnucp
lrwxrwxrwx   1 root root           5 Sep 26 18:16 df -> gnudf
lrwxrwxrwx   1 root root           5 Sep 26 18:16 mv -> gnumv
lrwxrwxrwx   1 root root           5 Sep 26 18:16 rm -> gnurm
lrwxrwxrwx   1 root root           7 Sep 26 18:16 true -> gnutrue

ubuntu@r:~$ ls -l /usr/bin | egrep "(\-> .*coreutils)"
lrwxrwxrwx   1 root root          28 Sep 26 18:16 [ -> ../lib/cargo/bin/coreutils/[
lrwxrwxrwx   1 root root          31 Sep 26 18:16 arch -> ../lib/cargo/bin/coreutils/arch
lrwxrwxrwx   1 root root          32 Sep 26 18:16 b2sum -> ../lib/cargo/bin/coreutils/b2sum
lrwxrwxrwx   1 root root          32 Sep 26 18:16 b3sum -> ../lib/cargo/bin/coreutils/b3sum
lrwxrwxrwx   1 root root          33 Sep 26 18:16 base32 -> ../lib/cargo/bin/coreutils/base32
lrwxrwxrwx   1 root root          33 Sep 26 18:16 base64 -> ../lib/cargo/bin/coreutils/base64
lrwxrwxrwx   1 root root          35 Sep 26 18:16 basename -> ../lib/cargo/bin/coreutils/basename
lrwxrwxrwx   1 root root          33 Sep 26 18:16 basenc -> ../lib/cargo/bin/coreutils/basenc
lrwxrwxrwx   1 root root          30 Sep 26 18:16 cat -> ../lib/cargo/bin/coreutils/cat
lrwxrwxrwx   1 root root          32 Sep 26 18:16 chcon -> ../lib/cargo/bin/coreutils/chcon
lrwxrwxrwx   1 root root          32 Sep 26 18:16 chgrp -> ../lib/cargo/bin/coreutils/chgrp
lrwxrwxrwx   1 root root          33 Sep 26 18:16 chroot -> ../lib/cargo/bin/coreutils/chroot
lrwxrwxrwx   1 root root          32 Sep 26 18:16 cksum -> ../lib/cargo/bin/coreutils/cksum
lrwxrwxrwx   1 root root          31 Sep 26 18:16 comm -> ../lib/cargo/bin/coreutils/comm
lrwxrwxrwx   1 root root          33 Sep 26 18:16 csplit -> ../lib/cargo/bin/coreutils/csplit
lrwxrwxrwx   1 root root          30 Sep 26 18:16 cut -> ../lib/cargo/bin/coreutils/cut
lrwxrwxrwx   1 root root          31 Sep 26 18:16 date -> ../lib/cargo/bin/coreutils/date
lrwxrwxrwx   1 root root          29 Sep 26 18:16 dd -> ../lib/cargo/bin/coreutils/dd
lrwxrwxrwx   1 root root          30 Sep 26 18:16 dir -> ../lib/cargo/bin/coreutils/dir
lrwxrwxrwx   1 root root          36 Sep 26 18:16 dircolors -> ../lib/cargo/bin/coreutils/dircolors
lrwxrwxrwx   1 root root          34 Sep 26 18:16 dirname -> ../lib/cargo/bin/coreutils/dirname
lrwxrwxrwx   1 root root          29 Sep 26 18:16 du -> ../lib/cargo/bin/coreutils/du
lrwxrwxrwx   1 root root          31 Sep 26 18:16 echo -> ../lib/cargo/bin/coreutils/echo
lrwxrwxrwx   1 root root          30 Sep 26 18:16 env -> ../lib/cargo/bin/coreutils/env
lrwxrwxrwx   1 root root          33 Sep 26 18:16 expand -> ../lib/cargo/bin/coreutils/expand
lrwxrwxrwx   1 root root          31 Sep 26 18:16 expr -> ../lib/cargo/bin/coreutils/expr
lrwxrwxrwx   1 root root          33 Sep 26 18:16 factor -> ../lib/cargo/bin/coreutils/factor
lrwxrwxrwx   1 root root          32 Sep 26 18:16 false -> ../lib/cargo/bin/coreutils/false
lrwxrwxrwx   1 root root          30 Sep 26 18:16 fmt -> ../lib/cargo/bin/coreutils/fmt
lrwxrwxrwx   1 root root          31 Sep 26 18:16 fold -> ../lib/cargo/bin/coreutils/fold
lrwxrwxrwx   1 root root          33 Sep 26 18:16 groups -> ../lib/cargo/bin/coreutils/groups
lrwxrwxrwx   1 root root          34 Sep 26 18:16 hashsum -> ../lib/cargo/bin/coreutils/hashsum
lrwxrwxrwx   1 root root          31 Sep 26 18:16 head -> ../lib/cargo/bin/coreutils/head
lrwxrwxrwx   1 root root          33 Sep 26 18:16 hostid -> ../lib/cargo/bin/coreutils/hostid
lrwxrwxrwx   1 root root          29 Sep 26 18:16 id -> ../lib/cargo/bin/coreutils/id
lrwxrwxrwx   1 root root          34 Sep 26 18:16 install -> ../lib/cargo/bin/coreutils/install
lrwxrwxrwx   1 root root          31 Sep 26 18:16 join -> ../lib/cargo/bin/coreutils/join
lrwxrwxrwx   1 root root          31 Sep 26 18:16 link -> ../lib/cargo/bin/coreutils/link
lrwxrwxrwx   1 root root          29 Sep 26 18:16 ln -> ../lib/cargo/bin/coreutils/ln
lrwxrwxrwx   1 root root          34 Sep 26 18:16 logname -> ../lib/cargo/bin/coreutils/logname
lrwxrwxrwx   1 root root          29 Sep 26 18:16 ls -> ../lib/cargo/bin/coreutils/ls
lrwxrwxrwx   1 root root          33 Sep 26 18:16 md5sum -> ../lib/cargo/bin/coreutils/md5sum
lrwxrwxrwx   1 root root          32 Sep 26 18:16 mkdir -> ../lib/cargo/bin/coreutils/mkdir
lrwxrwxrwx   1 root root          33 Sep 26 18:16 mkfifo -> ../lib/cargo/bin/coreutils/mkfifo
lrwxrwxrwx   1 root root          32 Sep 26 18:16 mknod -> ../lib/cargo/bin/coreutils/mknod
lrwxrwxrwx   1 root root          33 Sep 26 18:16 mktemp -> ../lib/cargo/bin/coreutils/mktemp
lrwxrwxrwx   1 root root          31 Sep 26 18:16 nice -> ../lib/cargo/bin/coreutils/nice
lrwxrwxrwx   1 root root          29 Sep 26 18:16 nl -> ../lib/cargo/bin/coreutils/nl
lrwxrwxrwx   1 root root          32 Sep 26 18:16 nohup -> ../lib/cargo/bin/coreutils/nohup
lrwxrwxrwx   1 root root          32 Sep 26 18:16 nproc -> ../lib/cargo/bin/coreutils/nproc
lrwxrwxrwx   1 root root          33 Sep 26 18:16 numfmt -> ../lib/cargo/bin/coreutils/numfmt
lrwxrwxrwx   1 root root          29 Sep 26 18:16 od -> ../lib/cargo/bin/coreutils/od
lrwxrwxrwx   1 root root          32 Sep 26 18:16 paste -> ../lib/cargo/bin/coreutils/paste
lrwxrwxrwx   1 root root          34 Sep 26 18:16 pathchk -> ../lib/cargo/bin/coreutils/pathchk
lrwxrwxrwx   1 root root          32 Sep 26 18:16 pinky -> ../lib/cargo/bin/coreutils/pinky
lrwxrwxrwx   1 root root          29 Sep 26 18:16 pr -> ../lib/cargo/bin/coreutils/pr
lrwxrwxrwx   1 root root          35 Sep 26 18:16 printenv -> ../lib/cargo/bin/coreutils/printenv
lrwxrwxrwx   1 root root          33 Sep 26 18:16 printf -> ../lib/cargo/bin/coreutils/printf
lrwxrwxrwx   1 root root          30 Sep 26 18:16 ptx -> ../lib/cargo/bin/coreutils/ptx
lrwxrwxrwx   1 root root          30 Sep 26 18:16 pwd -> ../lib/cargo/bin/coreutils/pwd
lrwxrwxrwx   1 root root          35 Sep 26 18:16 readlink -> ../lib/cargo/bin/coreutils/readlink
lrwxrwxrwx   1 root root          35 Sep 26 18:16 realpath -> ../lib/cargo/bin/coreutils/realpath
lrwxrwxrwx   1 root root          32 Sep 26 18:16 rmdir -> ../lib/cargo/bin/coreutils/rmdir
lrwxrwxrwx   1 root root          33 Sep 26 18:16 runcon -> ../lib/cargo/bin/coreutils/runcon
lrwxrwxrwx   1 root root          30 Sep 26 18:16 seq -> ../lib/cargo/bin/coreutils/seq
lrwxrwxrwx   1 root root          34 Sep 26 18:16 sha1sum -> ../lib/cargo/bin/coreutils/sha1sum
lrwxrwxrwx   1 root root          36 Sep 26 18:16 sha224sum -> ../lib/cargo/bin/coreutils/sha224sum
lrwxrwxrwx   1 root root          36 Sep 26 18:16 sha256sum -> ../lib/cargo/bin/coreutils/sha256sum
lrwxrwxrwx   1 root root          38 Sep 26 18:16 sha3-224sum -> ../lib/cargo/bin/coreutils/sha3-224sum
lrwxrwxrwx   1 root root          38 Sep 26 18:16 sha3-256sum -> ../lib/cargo/bin/coreutils/sha3-256sum
lrwxrwxrwx   1 root root          38 Sep 26 18:16 sha3-384sum -> ../lib/cargo/bin/coreutils/sha3-384sum
lrwxrwxrwx   1 root root          38 Sep 26 18:16 sha3-512sum -> ../lib/cargo/bin/coreutils/sha3-512sum
lrwxrwxrwx   1 root root          36 Sep 26 18:16 sha384sum -> ../lib/cargo/bin/coreutils/sha384sum
lrwxrwxrwx   1 root root          34 Sep 26 18:16 sha3sum -> ../lib/cargo/bin/coreutils/sha3sum
lrwxrwxrwx   1 root root          36 Sep 26 18:16 sha512sum -> ../lib/cargo/bin/coreutils/sha512sum
lrwxrwxrwx   1 root root          38 Sep 26 18:16 shake128sum -> ../lib/cargo/bin/coreutils/shake128sum
lrwxrwxrwx   1 root root          38 Sep 26 18:16 shake256sum -> ../lib/cargo/bin/coreutils/shake256sum
lrwxrwxrwx   1 root root          32 Sep 26 18:16 shred -> ../lib/cargo/bin/coreutils/shred
lrwxrwxrwx   1 root root          31 Sep 26 18:16 shuf -> ../lib/cargo/bin/coreutils/shuf
lrwxrwxrwx   1 root root          32 Sep 26 18:16 sleep -> ../lib/cargo/bin/coreutils/sleep
lrwxrwxrwx   1 root root          31 Sep 26 18:16 sort -> ../lib/cargo/bin/coreutils/sort
lrwxrwxrwx   1 root root          32 Sep 26 18:16 split -> ../lib/cargo/bin/coreutils/split
lrwxrwxrwx   1 root root          31 Sep 26 18:16 stat -> ../lib/cargo/bin/coreutils/stat
lrwxrwxrwx   1 root root          33 Sep 26 18:16 stdbuf -> ../lib/cargo/bin/coreutils/stdbuf
lrwxrwxrwx   1 root root          31 Sep 26 18:16 stty -> ../lib/cargo/bin/coreutils/stty
lrwxrwxrwx   1 root root          30 Sep 26 18:16 sum -> ../lib/cargo/bin/coreutils/sum
lrwxrwxrwx   1 root root          31 Sep 26 18:16 sync -> ../lib/cargo/bin/coreutils/sync
lrwxrwxrwx   1 root root          30 Sep 26 18:16 tac -> ../lib/cargo/bin/coreutils/tac
lrwxrwxrwx   1 root root          31 Sep 26 18:16 tail -> ../lib/cargo/bin/coreutils/tail
lrwxrwxrwx   1 root root          30 Sep 26 18:16 tee -> ../lib/cargo/bin/coreutils/tee
lrwxrwxrwx   1 root root          31 Sep 26 18:16 test -> ../lib/cargo/bin/coreutils/test
lrwxrwxrwx   1 root root          34 Sep 26 18:16 timeout -> ../lib/cargo/bin/coreutils/timeout
lrwxrwxrwx   1 root root          32 Sep 26 18:16 touch -> ../lib/cargo/bin/coreutils/touch
lrwxrwxrwx   1 root root          29 Sep 26 18:16 tr -> ../lib/cargo/bin/coreutils/tr
lrwxrwxrwx   1 root root          35 Sep 26 18:16 truncate -> ../lib/cargo/bin/coreutils/truncate
lrwxrwxrwx   1 root root          32 Sep 26 18:16 tsort -> ../lib/cargo/bin/coreutils/tsort
lrwxrwxrwx   1 root root          30 Sep 26 18:16 tty -> ../lib/cargo/bin/coreutils/tty
lrwxrwxrwx   1 root root          32 Sep 26 18:16 uname -> ../lib/cargo/bin/coreutils/uname
lrwxrwxrwx   1 root root          35 Sep 26 18:16 unexpand -> ../lib/cargo/bin/coreutils/unexpand
lrwxrwxrwx   1 root root          31 Sep 26 18:16 uniq -> ../lib/cargo/bin/coreutils/uniq
lrwxrwxrwx   1 root root          33 Sep 26 18:16 unlink -> ../lib/cargo/bin/coreutils/unlink
lrwxrwxrwx   1 root root          32 Sep 26 18:16 users -> ../lib/cargo/bin/coreutils/users
lrwxrwxrwx   1 root root          31 Sep 26 18:16 vdir -> ../lib/cargo/bin/coreutils/vdir
lrwxrwxrwx   1 root root          29 Sep 26 18:16 wc -> ../lib/cargo/bin/coreutils/wc
lrwxrwxrwx   1 root root          30 Sep 26 18:16 who -> ../lib/cargo/bin/coreutils/who
lrwxrwxrwx   1 root root          33 Sep 26 18:16 whoami -> ../lib/cargo/bin/coreutils/whoami
lrwxrwxrwx   1 root root          30 Sep 26 18:16 yes -> ../lib/cargo/bin/coreutils/yes

@Ecordonnier
Copy link
Collaborator

Ecordonnier commented Jan 8, 2026

Interesting.
On Ubuntu 24.04.03 it works:

ecordonnier@LBM9V6C4:~/dev/coreutils$ bash -c "exec -a foobar
/usr/lib/cargo/bin/coreutils/true"
foobar 0.0.24 (multi-call binary)

Usage: foobar [function [arguments...]]

Currently defined functions:

    [, arch, b2sum, b3sum, base32, base64, basename, basenc, cat,
chcon, chgrp, chmod, chown,
    chroot, cksum, comm, cp, csplit, cut, date, dd, df, dir,
dircolors, dirname, du, echo,
    env, expand, expr, factor, false, fmt, fold, groups, hashsum,
head, hostid, hostname, id,
    install, join, kill, link, ln, logname, ls, md5sum, mkdir, mkfifo,
mknod, mktemp, more,
    mv, nice, nl, nohup, nproc, numfmt, od, paste, pathchk, pinky, pr,
printenv, printf, ptx,
    pwd, readlink, realpath, rm, rmdir, runcon, seq, sha1sum,
sha224sum, sha256sum, sha3-
    224sum, sha3-256sum, sha3-384sum, sha3-512sum, sha384sum, sha3sum,
sha512sum, shake128sum,
    shake256sum, shred, shuf, sleep, sort, split, stat, stdbuf, sum,
sync, tac, tail, tee,
    test, timeout, touch, tr, true, truncate, tsort, tty, uname,
unexpand, uniq, unlink, uptime,
    users, vdir, wc, who, whoami, yes

On Ubuntu 26.04 (development branch) it doesn't work:

asteba@asteba-MS-7C75:~$ /usr/lib/cargo/bin/coreutils/true --version
/usr/lib/cargo/bin/coreutils/true (uutils coreutils) 0.2.2

asteba@asteba-MS-7C75:~$ bash -c "exec -a foobar /usr/lib/cargo/bin/coreutils/true"
Security violation: Requested utility `foobar` does not match executable name:
  /usr/lib/cargo/bin/coreutils/true

The error "Security Violation..." comes from uutils coreutils itself however I haven't found it in the source code:

asteba@asteba-MS-7C75:~$ strings /usr/lib/cargo/bin/coreutils/true | grep -i "Requested utility"
, src/bin/coreutils.rs[md5sumsha1sumsha224sumsha256sumsha384sumsha512sumsha3sumsha3-224sumsha3-256sumsha3-384sumsha3-512sumshake128sumshake256sumb2sumb3sumdirlshashsumLocalization parse error at Could not init the localization system: /proc/self/exeUnable to read /proc/self/exeCould not render filenameSecurity violation: Requested utility `` does not match executable name:

Edit: the error comes from a Ubuntu patch ( https://git.launchpad.net/ubuntu/+source/rust-coreutils/tree/debian/patches/require-utility-to-be-invoked-at-matching-path.patch?h=applied/ubuntu/devel ):

asteba@asteba-MS-7C75:~/dev/coreutils/ubuntu-sources$ rg -i "security violation" .
./rust-coreutils-0.2.2/debian/patches/require-utility-to-be-invoked-at-matching-path.patch
27:+                    "Security violation: Requested utility `{}` does not match executable name:\n  {}",

./rust-coreutils-0.2.2/src/bin/coreutils.rs
116:                    "Security violation: Requested utility `{}` does not match executable name:\n  {}",

@julian-klode FYI

@Ecordonnier
Copy link
Collaborator

@fnordahl I've created #10135 as follow-up, but it's not something which can be fixed in the uutils-coreutils repository itself, so I think this PR should be closed.

@Ecordonnier Ecordonnier closed this Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants